package IC.SymbolTable;

import IC.SemanticCheckes.SemanticError;

public class MethodSymbolTable extends BlockSymbolTable {

	public MethodSymbolTable(String name, ClassSymbolTable parent){
		super(parent);
		this.name = name;
		try{
			this.isStatic = parent.getMethodSymbol(name).isStatic();
		} catch(SemanticError se){

		}
	}
	
	public String getName(){
		return this.name;
	}
	
	//Override 
	public VarSymbol getVarSymbol(String name, int line) throws SemanticError{
		// parameters and local variables of method
		VarSymbol vs = varEntries.get(name); 
		if ( (line>0) && (vs != null)) {
			// defined later in the code
			if (vs.line > line)
				vs=null;
		}
		if (vs == null){
			if (this.isStatic){ 
				// this symbol table belongs to is a static method
				throw new SemanticError("name cannot be resolved",name);
			} else { 
				// this symbol table belongs to is a virtual method
				vs = ((ClassSymbolTable) parent).getFieldSymbol(name);
				vs.isDefined = true;
			}
		}
		return vs;
	}	
	
	//Override 
	public ClassSymbolTable getEnclosingClassSymbolTable(){
		return (ClassSymbolTable) parent;
	}	

	
	public VarSymbol getVarParamSymbol(String name) throws SemanticError{
		VarSymbol vps = varEntries.get(name);
		if (vps == null) {
			throw new SemanticError("variable/parameter does not exist in "+this.getName(), name);
		}
		else {
			return vps;
		}
	}

	
	public String toString(){
		String str = "Method Symbol Table: "+this.getName();
		
		// print list of parameters and local variables
		String pListStr = "";
		String lvListStr = "";
		for(VarSymbol vs: varEntries.values()){
			if (vs.getKind() == "PARAM"){ // parameter case
				pListStr += "\n\tParameter: "+vs.getType().getName()+" "+vs.getName();
			} else if (vs.getKind() != "RET_VAR"){ // local variable case
				lvListStr += "\n\tLocal variable: "+vs.getType().getName()+" "+vs.getName();
			}
		}
		str += pListStr+lvListStr;
		
		// print list of all children's blocks
		String path = "statement block in "+this.getName();
		
		if (!blockSymbolTableEntries.isEmpty()){
			str += "\nChildren tables: ";
			for(BlockSymbolTable bst: blockSymbolTableEntries)
				str += path+", ";
			str = str.substring(0, str.length()-2);
		}
		str += "\n\n";
		
		// print all the block symbol tables
		for(BlockSymbolTable bst: blockSymbolTableEntries){
			str += bst.toString(this.getName());
		}
		
		return str;
	}
	
	public boolean isVarField (String name){
		if (varEntries.containsKey(name)) return false;
		else return true;
	}
	
	public int getVarDepthRec(String name){
		int vd = varEntries.containsKey(name) ? this.getDepth() :
			((ClassSymbolTable) parent).getFieldDepthRec(name);
		return vd;
	}
	
	private String name;
	private boolean isStatic;
	
}
